﻿using Avalonia.Controls;
using LightCAD.Runtime.Interface;
using System.ComponentModel;

namespace LightCAD.Drawing.Actions.Action
{
    public class QuickSelectAction
    {
        protected DocumentRuntime docRt;
        public LcDocument lcDocument;
        public ViewportRuntime vportRt;
        protected IDocumentEditor docEditor;

        public bool isSelectedElement;
        public int elementCount;
        public HashSet<string> elementTypes = new HashSet<string>();

        private Dictionary<string, List<string>> eleType_Features = new Dictionary<string, List<string>>();
        private Dictionary<string, List<PropertyObserver>> eleType_Properties = new Dictionary<string, List<PropertyObserver>>();

        public HashSet<string> AllElementTypes { get { return eleType_Features.Keys.ToHashSet(); } }

        // 应用范围
        public string selectApply;
        // 对象类型
        public string selectType;
        // 特性
        public string selectFeature;
        // 运算符
        public string selectOperator;
        // 值
        public string selectOperatorValue;
        // 如何应用
        public bool selectApplyNew;
        // 附加
        public bool selectAdditional;

        public QuickSelectAction(IDocumentEditor docEditor)
        {
            this.docEditor = docEditor;
            this.docRt = docEditor.DocRt;
            this.vportRt = (docEditor as DrawingEditRuntime).ActiveViewportRt;
            this.lcDocument = docRt.Document;
        }

        public async void ExecCreate(string[] args)
        {
            List<LcElement> elements = docRt.Action.SelectedElements;
            isSelectedElement = true;
            elementCount = lcDocument.ModelSpace.Elements.Count;
            if (elements.Count == 0)
            {
                // 如果没有已选择元素，设置为所有元素
                elements = lcDocument.ModelSpace.Elements.ToList();
                // 是否已选择元素
                isSelectedElement = false;
            }

            // 元素类型
            foreach (var ele in elements)
            {
                elementTypes.Add(ele.Type.DispalyName);
            }

            var tempFeatures = GetElementFeature();
            eleType_Features.Add(AllTypeEnum.All.GetDescription(), tempFeatures.Select(s => s.DisplayName).ToList());
            eleType_Properties.Add(AllTypeEnum.All.GetDescription(), tempFeatures);
            foreach (var ele in lcDocument.ModelSpace.Elements.ToList())
            {
                if (eleType_Features.ContainsKey(ele.Type.DispalyName))
                {
                    break;
                }
                tempFeatures = GetElementFeature(ele.Type);
                eleType_Features.Add(ele.Type.DispalyName, tempFeatures.Select(s => s.DisplayName).ToList());
                eleType_Properties.Add(ele.Type.DispalyName, tempFeatures);
            }

            var win = (IQuickSelectWindow)AppRuntime.UISystem.CreateWindow("QuickSelectWindow", this);
            if (elementCount != 0)
            {
                var result = AppRuntime.UISystem.ShowDialog(win);
                if (result == LcDialogResult.OK)
                {
                    ExecQuickSelect();
                }
            }
        }

        private void ExecQuickSelect()
        {
            List<LcElement> applyElements = new List<LcElement>();
            List<LcElement> selectedElements = new List<LcElement>();

            // 应用范围
            ApplyRangeEnum applyRangeEnum = EnumExtensions.GetEnumValueFromDescription<ApplyRangeEnum>(selectApply);
            switch (applyRangeEnum) 
            {
                case ApplyRangeEnum.All:
                    applyElements = lcDocument.ModelSpace.Elements.ToList();
                    break;
                case ApplyRangeEnum.Selected:
                    applyElements = docRt.Action.SelectedElements.ToList();
                    break;
            }

            // 对象类型
            if (selectType != AllTypeEnum.All.GetDescription())
            {
                selectedElements = applyElements.FindAll(ele => ele.Type.DispalyName == selectType).ToList();
            }
            else
            {
                selectedElements = applyElements.ToList();
            }

            // 特性
            List<LcElement> resultEles = new List<LcElement>();
            var feaFeature = eleType_Properties[selectType];
            var property = feaFeature.FirstOrDefault(s => s.DisplayName == selectFeature);

            foreach (LcElement ele in selectedElements)
            {
                var value = property.Getter(ele);
                if (selectOperator == OperatorEnum.Equal.GetDescription())
                {
                    if (value.ToString() == selectOperatorValue)
                    {
                        resultEles.Add(ele);
                    }
                }
                else if (selectOperator == OperatorEnum.NoEqual.GetDescription())
                {
                    if (value.ToString() != selectOperatorValue)
                    {
                        resultEles.Add(ele);
                    }
                }
                else if (selectOperator == OperatorEnum.Greater.GetDescription())
                {
                    if (double.TryParse(value.ToString(), out double parseValue) 
                        && double.TryParse(value.ToString(), out double parseSelectOperatorValue)
                        && parseValue > parseSelectOperatorValue)
                    {
                        resultEles.Add(ele);
                    }
                }
                else if (selectOperator == OperatorEnum.Less.GetDescription())
                {
                    if (double.TryParse(value.ToString(), out double parseValue)
                        && double.TryParse(value.ToString(), out double parseSelectOperatorValue)
                        && parseValue < parseSelectOperatorValue)
                    {
                        resultEles.Add(ele);
                    }
                }
                else if (selectOperator == OperatorEnum.All.GetDescription())
                {
                    break;
                }
            }

            var selectResult = resultEles.ToList();
            // 是否附加
            if (selectAdditional)
            {
                selectResult.AddRange(docRt.Action.SelectedElements);
            }

            // 是否排除
            if (!selectApplyNew)
            {
                selectResult = applyElements.Except(resultEles).ToList();
            }

            // 清除现有选中 
            docRt.Action.ClearSelects();

            // 设置选中元素
            docRt.Action.SelectElements(docEditor, selectResult);
        }

        private List<PropertyObserver> GetElementFeature(ElementType? elementType = null)
        {
            List<PropertyObserver> features = new List<PropertyObserver>();
            var properties = PropertyAction.GetSharedPropertyObservers(docRt.Action);

            if (elementType != null)
            {
                var action = LcDocument.ElementActions[elementType];
                properties.AddRange((action as IPropertyObserver).GetPropertyObservers());
            }

            foreach (var item in properties)
            {
                features.Add(item);
            }

            return features;
        }

        public List<string> GetFeatures(string elementType = "")
        {
            if (elementType == "")
            {
                elementType = AllTypeEnum.All.GetDescription();
            }
            return eleType_Features[elementType];
        }
    }

    public enum ApplyRangeEnum
    {
        /// <summary>
        /// 整个图形
        /// </summary>
        [Description("整个图形")]
        All,
        /// <summary>
        /// 当前选择
        /// </summary>
        [Description("当前选择")]
        Selected,
    }

    public enum AllTypeEnum
    {
        /// <summary>
        /// 所有图元
        /// </summary>
        [Description("所有图元")]
        All,
    }

    public enum FeatureEnum
    {
        [Description("颜色")]
        ColorDropDown,
        [Description("图层|打印样式")]
        ComboBox,
        [Description("线型")]
        LineTypeDropDown,
        [Description("线宽")]
        LineWidthDropDown,
        [Description("其他")]
        TextBox,
    }

    public enum FeatureValueEnum
    {
        [Description("图层")]
        Layer,
        [Description("打印样式")]
        PrintStyle,
        [Description("材质")]
        Material,
    }

    public enum OperatorEnum
    {
        /// <summary>
        /// = 等于
        /// </summary>
        [Description("= 等于")]
        Equal,
        /// <summary>
        /// <> 不等于
        /// </summary>
        [Description("<> 不等于")]
        NoEqual,
        /// <summary>
        /// > 大于
        /// </summary>
        [Description("> 大于")]
        Greater,
        /// <summary>
        /// < 小于
        /// </summary>
        [Description("< 小于")]
        Less,
        /// <summary>
        /// 全部选择
        /// </summary>
        [Description("全部选择")]
        All,
    }
}
